﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Fees.cs" company="">
//   
// </copyright>
// <summary>
//   The fees.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using Systemathics.FrameWork.Interfaces;

namespace Systemathics.FrameWork
{
    internal class FeesConverter : ExpandableObjectConverter
    {
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType )
        {
            if (destType == typeof(string) && value is Fees)
            {
                var fees = (Fees)value;
                return fees.Broker; // ticker.Provider + ", " + ticker.Ric;
            }

            return base.ConvertTo(context, culture, value, destType);
        }
    }
    internal class ProvidersListConverter : TypeConverter
    {
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true; // display drop
        }

        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return true; // drop-down vs combo
        }
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            var NamesList = new List<string>();

            NamesList.AddRange(ProviderFactory.GetDataProvidersName(GlobalVariables.ASSEMBLY));
            NamesList.AddRange(ProviderFactory.GetOrderProvidersName(GlobalVariables.ASSEMBLY));
            NamesList.AddRange(ProviderFactory.GetMixedProvidersName(GlobalVariables.ASSEMBLY));
            return new StandardValuesCollection(NamesList);
        }
    }

    [TypeConverter(typeof(FeesConverter))]
    public sealed class Fees 
    {
        private readonly IFees fees;

        public Fees(DBInstruments dbi, IFees provider)
        {
            var attr = Attribute.GetCustomAttribute(provider.GetType(), typeof(BrokerFees)) as BrokerFees;
            provider.Broker = attr.Name;
            fees = provider;
            if (!dbi.DBFees.IsLoaded)
                dbi.DBFees.Load();
            var dbfee  = DBFees.CreateDBFees("NoFeesFound", Guid.NewGuid());
            var dbf = dbi.DBFees.Where(u => u.Broker == provider.Broker);
            if (dbf.Any())
                dbfee = dbf.FirstOrDefault();
            else
                new RemotingLogClient().Trace(new FireMessageEventArgs("Problem!!! no fees structure in db for: " + dbi.Name, Time.Now.TimeOfDay));

            fees.Broker = dbfee.Broker;
            fees.Borrow = (double)dbfee.Borrow;
            fees.Lending = (double)dbfee.Lend;
            fees.isPercentageFees = (bool)dbfee.isPercentageFees;
            fees.CancelFee = (double)dbfee.CancelFees;
            fees.MinExecFee = (double)dbfee.MinExecFee;
            fees.ModifFee = (double)dbfee.ModifyFees;
            fees.Crncy = dbfee.Crncy;
            fees.ExecFee = (double)dbfee.ExecFees;
            fees.IntradayInitialMargin = (double)dbfee.IntradayInitialMargin;
            fees.IntradayMaintenanceMargin = (double)dbfee.IntradayMaintenanceMargin;
            fees.OvernightInitialMargin = (double)dbfee.OvernightInitialMargin;
            fees.OvernightMaintenanceMargin = (double)dbfee.OvernightMaintenanceMargin;

            //Un peu idiot mais bon ...pas le choix..
            using (var db = new SystemathicsEntities(GlobalVariables.EntitiesConnectionString()))
            {
                var query = db.DBCurrency.Where(y => y.Ticker == fees.Crncy);
                if (query.Any())
                    ReferencePrice = (double)query.FirstOrDefault().ReferencePrice;
                else
                {
                    ReferencePrice = 1;
                    new RemotingLogClient().Trace(new FireMessageEventArgs("Unknown Currency Ticker for this Broker: " + fees.Broker + " - " + fees.Crncy, Time.Now.TimeOfDay));
                }
            }

            fees.MinExecFee = fees.MinExecFee * ReferencePrice;
            fees.TcInventory = 0;
            fees.Tc = 0;
        }

        #region IFees Members

        [TypeConverter(typeof(ProvidersListConverter))]
        public String Broker
        {
            get { return fees.Broker; }
            set
            {
                fees.Broker = value;
            }
        }
        public bool isPercentageFees
        {
            get
            {
                return fees.isPercentageFees;
            }
            set
            {
                fees.isPercentageFees = value;
            }
        }
        public double MinExecFee
        {
            get
            {
                return fees.MinExecFee;
            }
            set
            {
                fees.MinExecFee = value;
            }
        }
        public double ExecFee
        {
            get
            {
                return fees.ExecFee;
            }
            set
            {
                fees.ExecFee = value;
            }
        }
        public double ModifFee
        {
            get
            {
                return fees.ModifFee;
            }
            set
            {
                fees.ModifFee = value;
            }
        }
        public double CancelFee
        {
            get
            {
                return fees.CancelFee;
            }
            set
            {
                fees.CancelFee = value;
            }
        }
        public double IntradayInitialMargin
        {
            get
            {
                return fees.IntradayInitialMargin;
            }
            set
            {
                fees.IntradayInitialMargin = value;
            }
        }
        public double IntradayMaintenanceMargin
        {
            get
            {
                return fees.IntradayMaintenanceMargin;
            }
            set
            {
                fees.IntradayMaintenanceMargin = value;
            }
        }
        public double OvernightInitialMargin
        {
            get
            {
                return fees.OvernightInitialMargin;
            }
            set
            {
                fees.OvernightInitialMargin = value;
            }
        }
        public double OvernightMaintenanceMargin
        {
            get
            {
                return fees.OvernightMaintenanceMargin;
            }
            set
            {
                fees.OvernightMaintenanceMargin = value;
            }
        }
        public double Borrow
        {
            get
            {
                return fees.Borrow;
            }
            set
            {
                fees.Borrow = value;
            }
        }
        public double Lending
        {
            get
            {
                return fees.Lending;
            }
            set
            {
                fees.Lending = value;
            }
        }
        public string Crncy
        {
            get
            {
                return fees.Crncy;
            }
            set
            {
                fees.Crncy = value;
            }
        }
        public double InitialMargin
        {
            get
            {
                return fees.InitialMargin;
            }
            set
            {
                fees.InitialMargin = value;
            }
        }
        public double ReferencePrice
        {
            get
            {
                return fees.InitialMargin;
            }
            set
            {
                fees.ReferencePrice = value;
            }
        }
        public double Tc
        {
            get
            {
                return fees.Tc;
            }
            set
            {
                fees.Tc = value;
            }
        }
        public double TcInventory
        {
            get
            {
                return fees.TcInventory;
            }
            set
            {
                fees.TcInventory = value;
            }
        }

        public double Execution(int qty, Decimal price)
        {
            return fees.Execution(qty, price);
        }
        public double ExecutionInventory(int qty, Decimal price)
        {
            return fees.ExecutionInventory(qty, price);
        }
        public double Modification(int qty, Decimal price)
        {
            return fees.Modification(qty, price);
        }
        public double Cancellation(int qty, Decimal price)
        {
            return fees.Cancellation(qty, price);
        }

        #endregion

        public override string ToString()
        {
            return Broker;
        }
    }
}